#pragma once

#include "rank/RBTreeRank.h"

class Creature;
class Player;

class CreatureLooterMgr
{
public:
	CreatureLooterMgr(Creature* pCreature);
	~CreatureLooterMgr();

	void AddScore(Player* pPlayer, uint64 score);

	Player* CalcFinalLooter() const;

private:
	struct Looter {
		uint64 totalScore;
	};
	Creature* const m_pCreature;
	std::unordered_map<ObjGUID, Looter> m_allLooters;
};

class RankLooterMgr
{
public:
	RankLooterMgr(size_t maxRank);
	~RankLooterMgr();

	void AddScore(ObjGUID playerGuid,
		const std::string_view& playerName, uint64 score);

	const NetBuffer& GetRankCachePacket() const;
	std::pair<size_t, uint64> GetRank(ObjGUID playerGuid) const;

private:
	struct Looter {
		std::string playerName;
		uint64 totalScore;
	};
	static bool BetterLooter(const Looter& l1, const Looter& l2);
	const size_t m_maxRank;
	NetBuffer m_rankCachePacket;
	RBTreeRank<ObjGUID, Looter, decltype(&BetterLooter)> m_rankTree;
};

class TeamRankLooterMgr
{
public:
	TeamRankLooterMgr(size_t maxRank);
	~TeamRankLooterMgr();

	void AddScore(ObjGUID playerGuid, const std::string_view& playerName,
		uint32 teamId, const std::string_view& teamName, uint64 score);
	void ChangeTeam(ObjGUID playerGuid,
		uint32 teamId, const std::string_view& teamName);

	const NetBuffer& GetRankCachePacket() const;
	std::pair<size_t, uint64> GetRank(ObjGUID playerGuid) const;

private:
	void RebuildRankCachePacket();

	using RankGUID = uint64;
	static RankGUID RankGUID4Team(uint16 gsId, uint32 teamId);
	static RankGUID RankGUID4Player(ObjGUID playerGuid);

	struct Looter {
		std::string playerName;
		uint64 totalScore;
		uint32 teamId;
	};
	struct RankTeam {
		uint64 totalScore;
		std::string teamName;
		std::unordered_map<ObjGUID, const Looter*> teamMembers;
	};
	static bool BetterRankTeam(const RankTeam& rt1, const RankTeam& rt2);
	const size_t m_maxRank;
	std::map<ObjGUID, Looter> m_allLooters;
	NetBuffer m_rankCachePacket;
	RBTreeRank<RankGUID, RankTeam, decltype(&BetterRankTeam)> m_rankTree;
};
